<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Controller\admin;
use App\Exception\ValidateException;
use App\Controller\AbstractController;
use Hyperf\DbConnection\Db;
use App\Exception\HttpException;
use Hyperf\Filesystem\Exception\InvalidArgumentException;
use App\Model\admin\FilesModel;
use think\Image;


class UploadController extends CommonController
{
    
	protected $filesystem;
	
	
	public function __construct(\League\Flysystem\Filesystem $filesystem){
		$this->filesystem = $filesystem;
	}
	

	public function upload(){
		$file = $this->request->file('file');
		
		if(!$file->isValid()){
			throw new ValidateException("请选择有效的文件");
		}
		
		$filetype = cache()->get('base_config')['filetype'];
		if(!in_array(strtolower($file->getExtension()),explode(',',$filetype))){
			throw new ValidateException("文件类型验证失败");
		}
		
		if ($file->getSize() > cache()->get('base_config')['filesize'] * 1024 * 1024) {
		   throw new ValidateException("文件大小验证失败");
		}
		
		$filepath = $this->getFile($file);
		if($filepath){
			return json(['status'=>200,'data'=>$filepath,'filestatus'=>true]);
		}else{
			$edit = $this->request->post('edit');
			
			$filepath = $this->getFilePath($file);
			
			if(config('my.oss_status') && config('my.oss_upload_type') == 'client' && !$edit){
				switch(config('my.oss_default_type')){
					case 'qiniuyun';
						$data['serverurl'] = config('my.qny_oss_client_uploadurl');
						$data['domain'] = config('my.qny_oss_domain');
						$data['token'] = $this->getQnyToken();
					break;
					
					case 'tencent';
						$data['SecretId'] = config('my.tencent_oss_secretId');
						$data['SecretKey'] = config('my.tencent_oss_secretKey');
						$data['Bucket'] = config('my.tencent_oss_bucket');
						$data['Region'] = config('my.tencent_oss_region');
						$data['Schema'] = config('my.tencent_oss_schema');
					break;
					
					case 'ali':
						$options = array();
						$expire = 30;  //设置该policy超时时间是30s. 即这个policy过了这个有效时间，将不能访问。
						$now = time();
						$end = $now + $expire;
						$options['expiration'] = $this->gmtIso8601($end); /// 授权过期时间
						$conditions = array();
						array_push($conditions, array('bucket'=>config('my.ali_oss_bucket')));
						
						//$callbackUrl = 'http://b.cdlfvip.com/admin/Login/aliOssCallBack';	//oss异步回调地址，通过这个地址返回上传的文件名
						$callbackUrl = 'http://vue2.whpj.vip/admin/Login/aliOssCallBack';

						$callback_param = array('callbackUrl'=>$callbackUrl,
							'callbackBody'=>'${object}',
							'callbackBodyType'=>"application/x-www-form-urlencoded");
						$callback_string = json_encode($callback_param);

						$base64_callback_body = base64_encode($callback_string);
						
						$content_length_range = array();
						array_push($content_length_range, 'content-length-range');
						array_push($content_length_range, 0);
						array_push($content_length_range, 2048 * 1024 * 1024);
						array_push($conditions, $content_length_range);
						$options['conditions'] = $conditions;
						$policy = base64_encode(stripslashes(json_encode($options)));
						$sign = base64_encode(hash_hmac('sha1',$policy,config('my.ali_oss_accessKeySecret'), true));
						
						$data['serverurl'] = $this->getendpoint(config('my.ali_oss_endpoint'));
						$data['sign'] = $sign;
						$data['policy'] = $policy;
						$data['callback'] = $base64_callback_body;
						$data['OSSAccessKeyId'] = config('my.ali_oss_accessKeyId');
					break;
				}
				$data['key'] = $filepath;
				$data['type'] = config('my.oss_default_type');
				return json(['status'=>200,'data'=>$data]);
			}else{
				if($url = $this->up($file,$filepath)){
					return json(['status'=>200,'data'=>$url]);
				}
			}
		}
	}
	
	
	private function up($file,$filepath){
        $stream = fopen($file->getRealPath(), 'r+');
		try{
			if(config('my.oss_status')){
				$url = \App\Utils\Oss\OssService::OssUpload($file,$filepath);
				$disk = config('my.oss_default_type');
			}else{
				$this->filesystem->writeStream($filepath,$stream);
				$url = cache()->get('base_config')['domain'].'/'.$filepath;
				fclose($stream);
				
				$disk = 'local';
			}
		}catch(InvalidArgumentException $e){
			throw new HttpException($e->getError());
		}
		
		$data = ['filepath'=>$url,'hash'=>$this->hash('md5',$file),'create_time'=>time(),'disk'=>$disk];
		if($url && explode('/',$file->getMimeType())[0] == 'image'){
			$data['type'] = 1;
		}
		FilesModel::insert($data);
		
		return $url;
	}
	
	
	//获取文件存储路径
	private function getFilePath($file){
		$filename = $this->hash('md5',$file).'.'.$file->getExtension();
		$filepath = 'uploads/admin/'.date('Ym').'/'.$filename;
		return $filepath;
	}
	
	
	//检测数据库的同图片的路径是否存在 存在则返回
	private function getFile($file){
		$filepath = FilesModel::where('hash',$this->hash('md5',$file))->value('filepath');
		if($filepath  && config('my.check_file_status')){
			return $filepath;
		}
	}
	
	
	//oss上传成功后写入图片路径
	public function createFile(){
		$filepath = $this->request->input('filepath');
		$disk = $this->request->input('disk');
		$hash = explode('.',basename($filepath))[0];
		$data = ['filepath'=>$filepath,'hash'=>$hash,'create_time'=>time(),'disk'=>$disk];
		if($filepath  && in_array(explode('.',basename($filepath))[1],['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'])){
			$data['type'] = 1;
		}
		Db::table('file')->insert($data);
		return json(['status'=>200]);
	}
	
	
	/**
     * 获取文件的哈希散列值
     * @access public
     * @param string $type
     * @return string
     */
    public function hash(string $type,$file): string
    {
        return hash_file($type, $file->getRealPath());
    }
	
	
	//获取七牛云上传的token
	private function getQnyToken(){
		$auth = new \Qiniu\Auth(config('my.qny_oss_accessKey'), config('my.qny_oss_secretKey'));
		$upToken = $auth->uploadToken(config('my.qny_oss_bucket'));
		return $upToken;
	}
	
	
	//获取阿里云oss客户端上传地址
	private function getendpoint($str){
		if(strpos(config('my.ali_oss_endpoint'),'aliyuncs.com') !== false){
			if(strpos($str,'https') !== false){
				$point = 'https://'.config('my.ali_oss_bucket').'.'.substr($str,8);
			}else{
				$point = 'http://'.config('my.ali_oss_bucket').'.'.substr($str,7);
			}	
		}else{
			$point = config('my.ali_oss_endpoint');
		}
		return $point;
	}
	
	
	//阿里云oss客户端上传 授权过期时间
	private function gmtIso8601($time) {
        $dtStr = date("c", $time);
        $mydatetime = new \DateTime($dtStr);
        $expiration = $mydatetime->format(\DateTime::ISO8601);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }
	

	
}
